package cn.wolfcode.business.service.impl;

import cn.wolfcode.business.domain.BusAudit;
import cn.wolfcode.business.domain.BusBpmnInfo;
import cn.wolfcode.business.domain.BusServiceItem;
import cn.wolfcode.business.domain.vo.AduitVo;
import cn.wolfcode.business.domain.vo.AuditInfoVO;
import cn.wolfcode.business.mapper.BusServiceItemMapper;
import cn.wolfcode.business.service.BusAuditService;
import cn.wolfcode.business.service.BusBpmnInfoService;
import cn.wolfcode.business.service.BusServiceItemService;
import cn.wolfcode.common.core.domain.entity.SysUser;
import cn.wolfcode.common.utils.SecurityUtils;
import cn.wolfcode.system.service.ISysConfigService;
import cn.wolfcode.system.service.ISysRoleService;
import cn.wolfcode.system.service.ISysUserService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.wolfcode.business.domain.BusAudit.FLOW_AUDIT_TYPE;
import static cn.wolfcode.business.domain.BusAudit.STATUS_IN_PROGRESS;
import static cn.wolfcode.business.domain.BusServiceItem.*;

@Service
public class BusServiceItemServiceImpl implements BusServiceItemService {

    @Autowired
    BusServiceItemMapper busServiceItemMapper;
    @Autowired
    ISysUserService iSysUserService;
    @Autowired
    ISysConfigService iSysConfigService;
    @Autowired
    RuntimeService runtimeService;
    @Autowired
    BusBpmnInfoService busBpmnInfoService;
    @Autowired
    BusAuditService busAuditService;


    /**
     * 查询所有的服务项列表
     *
     * @param busServiceItem
     * @return
     */
    @Override
    public List<BusServiceItem> getList(BusServiceItem busServiceItem) {
        return busServiceItemMapper.getList(busServiceItem);
    }

    /**
     * 查询一条服务项列表用于回显数据
     *
     * @param id
     * @return
     */
    @Override
    public BusServiceItem getBusServiceItem(Long id) {
        return busServiceItemMapper.getBusServiceItem(id);
    }

    /**
     * 新增一条数据项数据
     *
     * @param busServiceItem
     * @return
     */
    @Override
    public Integer add(BusServiceItem busServiceItem) {
        /*
        首先进行参数合理化验证
         */
        //1.非空验证
        if (busServiceItem.getName() == null || busServiceItem.getOriginalPrice() == null
                || busServiceItem.getDiscountPrice() == null || busServiceItem.getCarPackage() == null
                || busServiceItem.getServiceCatalog() == null || busServiceItem.getInfo() == null)
            throw new RuntimeException("必填数据不能为空！！！");
        //2.原价和折扣价验证 --- 0<=折扣价<=原价   注意BigDecimal类需要使用方法进行操作
        //compareTo方法的返回值，当大于（）值返回 1，小于返回-1 ，等于返回 0
        if (busServiceItem.getDiscountPrice().compareTo(new BigDecimal(BigInteger.ZERO)) == -1 ||
                busServiceItem.getOriginalPrice().compareTo(busServiceItem.getDiscountPrice()) == -1)
            throw new RuntimeException("价格设置不合理，价格必须大于0且折扣价必须小于等于原价！！！");
        //3.根据是否套餐决定其 审核状态，若不是套餐则审核状态为无需审核，若为套餐则审核状态为初始化
        //确保数据安全创建一个中间对象接受我们需要的参数
        BusServiceItem newBusServiceItem = new BusServiceItem();
        if (CARPACKAGE_NO.equals(busServiceItem.getCarPackage())) {
            //若不是套餐,设置为无需审核
            newBusServiceItem.setAuditStatus(AUDITSTATUS_NO_REQUIRED);
        } else {
            //若是套餐，设置为初始化
            newBusServiceItem.setAuditStatus(AUDITSTATUS_INIT);
        }
        newBusServiceItem.setName(busServiceItem.getName());
        newBusServiceItem.setOriginalPrice(busServiceItem.getOriginalPrice());
        newBusServiceItem.setDiscountPrice(busServiceItem.getDiscountPrice());
        //是否套餐carPackage
        newBusServiceItem.setCarPackage(busServiceItem.getCarPackage());
        newBusServiceItem.setInfo(busServiceItem.getInfo());
        newBusServiceItem.setServiceCatalog(busServiceItem.getServiceCatalog());
        //上架状态均设置为未上架
        newBusServiceItem.setSaleStatus(SALESTATUS_OFF);
        newBusServiceItem.setCreateTime(new Date());
        return busServiceItemMapper.add(newBusServiceItem);
    }

    /**
     * 编辑服务项数据
     *
     * @param busServiceItem
     * @return
     */
    @Override
    public Integer update(BusServiceItem busServiceItem) {
  /*
        首先进行参数合理化验证
         */
        //1.非空验证
        if (busServiceItem.getName() == null || busServiceItem.getOriginalPrice() == null
                || busServiceItem.getDiscountPrice() == null || busServiceItem.getCarPackage() == null
                || busServiceItem.getServiceCatalog() == null || busServiceItem.getInfo() == null)
            throw new RuntimeException("必填数据不能为空！！！");
        //2.原价和折扣价验证 --- 0<=折扣价<=原价   注意BigDecimal类需要使用方法进行操作
        //compareTo方法的返回值，当大于（）值返回 1，小于返回-1 ，等于返回 0
        if (busServiceItem.getDiscountPrice().compareTo(new BigDecimal(BigInteger.ZERO)) == -1 ||
                busServiceItem.getOriginalPrice().compareTo(busServiceItem.getDiscountPrice()) == -1)
            throw new RuntimeException("价格设置不合理，价格必须大于0且折扣价必须小于等于原价！！！");
        //3.编辑不让改是否套餐的选项
        //为了保证安全再次设置是否套餐的值为原值
        if (!getBusServiceItem(busServiceItem.getId()).getCarPackage().equals(busServiceItem.getCarPackage())) {
            throw new RuntimeException("非法操作数据！！！！");
        }
        busServiceItem.setCarPackage(getBusServiceItem(busServiceItem.getId()).getCarPackage());
        //4.什么时候能够修改--上架状态的商品禁止修改，
        // 是套餐且为初始化状态可以修改
        // 是套餐且为审批通过或审批拒绝可以修改
        //是套餐且状态为审批中不让修改
        //是否套餐
        Integer carPackage = getBusServiceItem(busServiceItem.getId()).getCarPackage();
        //审核状态
        Integer auditStatus = getBusServiceItem(busServiceItem.getId()).getAuditStatus();
        //上架状态
        Integer saleStatus = getBusServiceItem(busServiceItem.getId()).getSaleStatus();
        if (SALESTATUS_ON.equals(saleStatus)) {
            throw new RuntimeException("上架状态不允许进行编辑，请先下架！！！！");
        }

        if (AUDITSTATUS_AUDITING.equals(auditStatus)) {
            throw new RuntimeException("审核中的套餐，不能够进行编辑！！！！");
        }
        //审核通过的可以修改，修改后的状态变为初始化
        if (AUDITSTATUS_APPROVED.equals(auditStatus)) {
            busServiceItem.setAuditStatus(AUDITSTATUS_INIT);
        }
        return busServiceItemMapper.update(busServiceItem);
    }

    /**
     * 上架业务逻辑
     * 什么时候能上架，只有下架才能上架
     * 并且状态是无需审核和审核通过才能下架
     *
     * @param id
     * @return
     */
    @Override
    public Integer puton(Long id) {
        //参数合理化验证
        if (id == null)
            throw new RuntimeException("非法参数");
        //是否上下架
        Integer saleStatus = getBusServiceItem(id).getSaleStatus();
        //审核状态
        Integer auditStatus = getBusServiceItem(id).getAuditStatus();
        if (SALESTATUS_ON.equals(saleStatus))
            throw new RuntimeException("只有下架商品才能上架");
        if (!AUDITSTATUS_APPROVED.equals(auditStatus) && !AUDITSTATUS_NO_REQUIRED.equals(auditStatus))
            throw new RuntimeException("只有审核通过后或者无需审核才能上架");
        return busServiceItemMapper.puton(id, SALESTATUS_ON);
    }

    @Override
    public Integer putoff(Long id) {
        //参数合理化验证
        if (id == null)
            throw new RuntimeException("非法参数");
        //是否上下架
        Integer saleStatus = getBusServiceItem(id).getSaleStatus();
        //审核状态
        Integer auditStatus = getBusServiceItem(id).getAuditStatus();
        if (SALESTATUS_OFF.equals(saleStatus))
            throw new RuntimeException("只有上架商品才能下架");
        return busServiceItemMapper.putoff(id, SALESTATUS_OFF);
    }

    /**
     * @param id
     * @return 发起审核前的数据回显，
     * 返回服务项的 服务项名称，原价，折扣价
     * 店长列表
     * 财务列表
     * 阈值
     */

    @Override
    public AuditInfoVO startAudit(Long id) {
        //1.参数合理化校验
        if (id == null) {
            throw new RuntimeException("非法参数");
        }
        AuditInfoVO vo = new AuditInfoVO();
        //1.根据服务项id查询服务项的服务名称，原价，折扣价
        BusServiceItem busServiceItem = busServiceItemMapper.getBusServiceItem(id);
        vo.setServiceItem(busServiceItem);
        //2.查询店长列表--根据role_key查询对应权限的用户
        List<SysUser> shopOwner = iSysUserService.selectUserByRoleKey("shopOwner");
        vo.setShopOwners(shopOwner);
        //3.查询财务列表
        List<SysUser> finance = iSysUserService.selectUserByRoleKey("finance");
        vo.setFinances(finance);
        //4.查询出阈值
        String discountPriceLimit = iSysConfigService.selectConfigByKey("discountPriceLimit");
        vo.setDiscountPrice(new BigDecimal(discountPriceLimit));
        return vo;
    }

    /**
     * 发起审核创建一个流程实例
     * 同时向套餐审核中添加数据 同步状态
     *
     * @param aduitVo
     * @return
     */
    @Transactional
    @Override
    public Integer startAuditSubmit(AduitVo aduitVo) {
        //参数合理化验证
        if (aduitVo == null) {
            throw new RuntimeException("非法参数！");
        }
        if (aduitVo.getServiceItemId() == null || aduitVo.getShopOwenerId() == null) {
            throw new RuntimeException("非法参数！");
        }
        //1.首先需要插入数据得到回填主键-需要出入的服务项数据有 id，名称，服务项备注，状态手动更改为审核中，创建时间，
        //1.1根据服务项id查询到服务项对象
        BusServiceItem busServiceItem = busServiceItemMapper.getBusServiceItem(aduitVo.getServiceItemId());
        //对服务项状态进行验证，必须是套餐，下架，初始化状态才能进行审核
        if (!(CARPACKAGE_YES.equals(busServiceItem.getCarPackage())
                && SALESTATUS_OFF.equals(busServiceItem.getSaleStatus())
                && AUDITSTATUS_INIT.equals(busServiceItem.getAuditStatus()))) {
            throw  new RuntimeException("只有套餐，并且已下架的商品，且审核状态是初始化的商品才能发起审核！");
        }
        //1.2把服务项中的数据给中间表对象
        BusAudit busAudit = new BusAudit();
        busAudit.setServiceItemId(aduitVo.getServiceItemId());//服务项id
        busAudit.setServiceItemName(busServiceItem.getName());//服务项名称
        busAudit.setServiceItemInfo(busServiceItem.getInfo());//服务项备注
        busAudit.setServiceItemPrice(busServiceItem.getDiscountPrice());//服务项折扣价格
        busAudit.setCreatorId(SecurityUtils.getUserId().toString());//创建者id
        busAudit.setInfo(aduitVo.getInfo());//快照表备注
        busAudit.setStatus(STATUS_IN_PROGRESS);//状态设置为审核中
        busAudit.setCreateTime(new Date());
        //先向中间表中插入数据
        busAuditService.insert(busAudit);
        String businessKey = busAudit.getId().toString();
        //2.启动流程实例绑定businessKey,但是启动流程实例需要流程定义的key或者id
        //需要根据发起的流程类型来或得
        BusBpmnInfo busBpmnInfo = busBpmnInfoService.selectProcessInstanceByBpmnType(FLOW_AUDIT_TYPE);
        //3.设置审批人
        Map<String,Object> params=new HashMap<>();
        params.put("shopOwnerId",aduitVo.getShopOwenerId());
        if (aduitVo.getFinanceId()!=null){
            params.put("financeId",aduitVo.getFinanceId());
        }
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(busBpmnInfo.getProcessDefinitionKey(), businessKey, params);
        //3.启动后得到流程实例id，将快照表中的流程实例id进行更新
        busAuditService.updateInstanceId(busAudit.getId(),processInstance.getProcessInstanceId());
        //4.最后更新服务项表中的状态
        return busServiceItemMapper.updateStatus(aduitVo.getServiceItemId(),AUDITSTATUS_AUDITING);
    }

    @Override
    public Integer updateAuditStatus(Long id, Integer auditstatusInit) {
        return busServiceItemMapper.updateAuditStatus( id,  auditstatusInit);
    }

}
